Packages R sur RForge

Une liste des packages est disponible sur la page d'accueil http://rforge.net. Nous allons parser cette liste afin de récupérer chaque nom de package, et ensuite nous téléchargeons les meta-data associées à chaque package.

Ces meta-data sont accessibles directement en ligne. Par exemple, pour le package Acinonyx, le fichier est disponible à l'adresse suivante : http://svn.rforge.net/Acinonyx/trunk/DESCRIPTION


In [1]:
import requests
import BeautifulSoup as bs

PKG_LIST_URL = 'http://rforge.net'
PKG_DETAILS_URL = 'http://svn.rforge.net/{name}/trunk/DESCRIPTION'

In [2]:
content = requests.get(PKG_LIST_URL).content
soup = bs.BeautifulSoup(content)

In [3]:
table = soup.find('b', text='Current projects').findNext('table')
anchors = filter(lambda x: x, (row.find('a') for row in table.findAll('tr') if row))
urls = map(lambda a: a['href'], anchors)
packages = map(lambda u: u[1:-1], urls)

In [4]:
packages[:10]


Out[4]:
[u'Acinonyx',
 u'actogram',
 u'affinity',
 u'ALA4R',
 u'animation',
 u'AntBioR',
 u'Arduino',
 u'audio',
 u'background',
 u'base64enc']

Nous allons maintenant récupérer les fichiers descriptions. Nous les parserons directement dans un dictionnaire, afin de générer un joli petit fichier .csv avec pandas à la fin.


In [5]:
d = {}
err404 = []

for name in packages:
    r = requests.get(PKG_DETAILS_URL.format(name=name))
    if r.status_code != 200:
        err404.append(name)
    else:
        d[name] = {}
        for line in r.content.split('\n'):
            if len(line) > 0:
                # Si la ligne débute par des tabulations ou espace, continuation de la ligne précédente
                if line.startswith((' ', '\t')):
                    d[name][key] += ' ' + line.strip()   # key a encore la bonne valeur
                else:
                    try:
                        key, value = line.split(':', 1)
                        d[name][key.strip()] = value.strip()
                    except Exception as e:
                        print name
                        print line
                        print '---'
                        print content
                        raise

In [6]:
len(d), len(err404), len(packages)


Out[6]:
(81, 60, 141)

In [14]:
import pandas

pandas.DataFrame.from_dict(d, orient='index').to_csv('../data/rforge_description.csv')